﻿ 
 
namespace ChessKit.Logic
{
  partial class Board
  {
    private MoveHints ValidateWhiteBishopMove(int fromSquare, int toSquare)
    {
	  var dx = toSquare - fromSquare;
	  if (dx < 0)
	  {
        if (dx % 17 == 0) 
        {
          for (var i = fromSquare - 17; i > toSquare; i -= 17)
            if (Squares[i] != 0) return MoveHints.Bishop | MoveHints.DoesNotJump;
          return MoveHints.Bishop;
        }
        if (dx % 15 == 0) 
        {
          for (var i = fromSquare - 15; i > toSquare; i -= 15)
            if (Squares[i] != 0) return MoveHints.Bishop | MoveHints.DoesNotJump;
          return MoveHints.Bishop;
        }
	  }
	  else
	  {
        if (dx % 17 == 0) 
        {
          for (var i = fromSquare + 17; i < toSquare; i += 17)
            if (Squares[i] != 0) return MoveHints.Bishop | MoveHints.DoesNotJump;
          return MoveHints.Bishop;
        }
        if (dx % 15 == 0) 
        {
          for (var i = fromSquare + 15; i < toSquare; i += 15)
            if (Squares[i] != 0) return MoveHints.Bishop | MoveHints.DoesNotJump;
          return MoveHints.Bishop;
        }
      }
      return MoveHints.Bishop | MoveHints.DoesNotMoveThisWay;
    }
    private static MoveHints ValidateWhiteKnightMove(int fromSquare, int toSquare)
    {
	  var dx = toSquare - fromSquare;
      switch (dx)
      {      
        case 33:
          return MoveHints.Knight;
        case 31:
          return MoveHints.Knight;
        case -31:
          return MoveHints.Knight;
        case -33:
          return MoveHints.Knight;
        case 18:
          return MoveHints.Knight;
        case 14:
          return MoveHints.Knight;
        case -14:
          return MoveHints.Knight;
        case -18:
          return MoveHints.Knight;
      }
	  return MoveHints.Knight | MoveHints.DoesNotMoveThisWay;
    }
    private MoveHints ValidateWhiteRookMove(int fromSquare, int toSquare)
    {
	  var dx = toSquare - fromSquare;
	  if (dx < 0)
	  {
        if (dx % 16 == 0) 
        {
          for (var i = fromSquare - 16; i > toSquare; i -= 16)
            if (Squares[i] != 0) return MoveHints.Rook | MoveHints.DoesNotJump;
          return MoveHints.Rook;
        }
        if (dx > -8) 
        {
          for (var i = fromSquare - 1; i > toSquare; i -= 1)
            if (Squares[i] != 0) return MoveHints.Rook | MoveHints.DoesNotJump;
          return MoveHints.Rook;
        }
	  }
	  else
	  {
        if (dx % 16 == 0) 
        {
          for (var i = fromSquare + 16; i < toSquare; i += 16)
            if (Squares[i] != 0) return MoveHints.Rook | MoveHints.DoesNotJump;
          return MoveHints.Rook;
        }
        if (dx < 8) 
        {
          for (var i = fromSquare + 1; i < toSquare; i += 1)
            if (Squares[i] != 0) return MoveHints.Rook | MoveHints.DoesNotJump;
          return MoveHints.Rook;
        }
      }
      return MoveHints.Rook | MoveHints.DoesNotMoveThisWay;
    }
    private MoveHints ValidateWhiteQueenMove(int fromSquare, int toSquare)
    {
	  var dx = toSquare - fromSquare;
	  if (dx < 0)
	  {
        if (dx % 17 == 0) 
        {
          for (var i = fromSquare - 17; i > toSquare; i -= 17)
            if (Squares[i] != 0) return MoveHints.Queen | MoveHints.DoesNotJump;
          return MoveHints.Queen;
        }
        if (dx % 16 == 0) 
        {
          for (var i = fromSquare - 16; i > toSquare; i -= 16)
            if (Squares[i] != 0) return MoveHints.Queen | MoveHints.DoesNotJump;
          return MoveHints.Queen;
        }
        if (dx % 15 == 0) 
        {
          for (var i = fromSquare - 15; i > toSquare; i -= 15)
            if (Squares[i] != 0) return MoveHints.Queen | MoveHints.DoesNotJump;
          return MoveHints.Queen;
        }
        if (dx > -8) 
        {
          for (var i = fromSquare - 1; i > toSquare; i -= 1)
            if (Squares[i] != 0) return MoveHints.Queen | MoveHints.DoesNotJump;
          return MoveHints.Queen;
        }
	  }
	  else
	  {
        if (dx % 17 == 0) 
        {
          for (var i = fromSquare + 17; i < toSquare; i += 17)
            if (Squares[i] != 0) return MoveHints.Queen | MoveHints.DoesNotJump;
          return MoveHints.Queen;
        }
        if (dx % 16 == 0) 
        {
          for (var i = fromSquare + 16; i < toSquare; i += 16)
            if (Squares[i] != 0) return MoveHints.Queen | MoveHints.DoesNotJump;
          return MoveHints.Queen;
        }
        if (dx % 15 == 0) 
        {
          for (var i = fromSquare + 15; i < toSquare; i += 15)
            if (Squares[i] != 0) return MoveHints.Queen | MoveHints.DoesNotJump;
          return MoveHints.Queen;
        }
        if (dx < 8) 
        {
          for (var i = fromSquare + 1; i < toSquare; i += 1)
            if (Squares[i] != 0) return MoveHints.Queen | MoveHints.DoesNotJump;
          return MoveHints.Queen;
        }
      }
      return MoveHints.Queen | MoveHints.DoesNotMoveThisWay;
    }
    private static MoveHints ValidateWhiteKingMove(int fromSquare, int toSquare)
    {
	  var dx = toSquare - fromSquare;
      switch (dx)
      {      
        case 16:
          return MoveHints.King;
        case 17:
          return MoveHints.King;
        case 1:
          return MoveHints.King;
        case -15:
          return MoveHints.King;
        case -16:
          return MoveHints.King;
        case -17:
          return MoveHints.King;
        case -1:
          return MoveHints.King;
        case 15:
          return MoveHints.King;
      }
	  return MoveHints.King | MoveHints.DoesNotMoveThisWay;
    }
    private MoveHints ValidateBlackBishopMove(int fromSquare, int toSquare)
    {
	  var dx = toSquare - fromSquare;
	  if (dx < 0)
	  {
        if (dx % 17 == 0) 
        {
          for (var i = fromSquare - 17; i > toSquare; i -= 17)
            if (Squares[i] != 0) return MoveHints.Bishop | MoveHints.DoesNotJump;
          return MoveHints.Bishop;
        }
        if (dx % 15 == 0) 
        {
          for (var i = fromSquare - 15; i > toSquare; i -= 15)
            if (Squares[i] != 0) return MoveHints.Bishop | MoveHints.DoesNotJump;
          return MoveHints.Bishop;
        }
	  }
	  else
	  {
        if (dx % 17 == 0) 
        {
          for (var i = fromSquare + 17; i < toSquare; i += 17)
            if (Squares[i] != 0) return MoveHints.Bishop | MoveHints.DoesNotJump;
          return MoveHints.Bishop;
        }
        if (dx % 15 == 0) 
        {
          for (var i = fromSquare + 15; i < toSquare; i += 15)
            if (Squares[i] != 0) return MoveHints.Bishop | MoveHints.DoesNotJump;
          return MoveHints.Bishop;
        }
      }
      return MoveHints.Bishop | MoveHints.DoesNotMoveThisWay;
    }
    private static MoveHints ValidateBlackKnightMove(int fromSquare, int toSquare)
    {
	  var dx = toSquare - fromSquare;
      switch (dx)
      {      
        case 33:
          return MoveHints.Knight;
        case 31:
          return MoveHints.Knight;
        case -31:
          return MoveHints.Knight;
        case -33:
          return MoveHints.Knight;
        case 18:
          return MoveHints.Knight;
        case 14:
          return MoveHints.Knight;
        case -14:
          return MoveHints.Knight;
        case -18:
          return MoveHints.Knight;
      }
	  return MoveHints.Knight | MoveHints.DoesNotMoveThisWay;
    }
    private MoveHints ValidateBlackRookMove(int fromSquare, int toSquare)
    {
	  var dx = toSquare - fromSquare;
	  if (dx < 0)
	  {
        if (dx % 16 == 0) 
        {
          for (var i = fromSquare - 16; i > toSquare; i -= 16)
            if (Squares[i] != 0) return MoveHints.Rook | MoveHints.DoesNotJump;
          return MoveHints.Rook;
        }
        if (dx > -8) 
        {
          for (var i = fromSquare - 1; i > toSquare; i -= 1)
            if (Squares[i] != 0) return MoveHints.Rook | MoveHints.DoesNotJump;
          return MoveHints.Rook;
        }
	  }
	  else
	  {
        if (dx % 16 == 0) 
        {
          for (var i = fromSquare + 16; i < toSquare; i += 16)
            if (Squares[i] != 0) return MoveHints.Rook | MoveHints.DoesNotJump;
          return MoveHints.Rook;
        }
        if (dx < 8) 
        {
          for (var i = fromSquare + 1; i < toSquare; i += 1)
            if (Squares[i] != 0) return MoveHints.Rook | MoveHints.DoesNotJump;
          return MoveHints.Rook;
        }
      }
      return MoveHints.Rook | MoveHints.DoesNotMoveThisWay;
    }
    private MoveHints ValidateBlackQueenMove(int fromSquare, int toSquare)
    {
	  var dx = toSquare - fromSquare;
	  if (dx < 0)
	  {
        if (dx % 17 == 0) 
        {
          for (var i = fromSquare - 17; i > toSquare; i -= 17)
            if (Squares[i] != 0) return MoveHints.Queen | MoveHints.DoesNotJump;
          return MoveHints.Queen;
        }
        if (dx % 16 == 0) 
        {
          for (var i = fromSquare - 16; i > toSquare; i -= 16)
            if (Squares[i] != 0) return MoveHints.Queen | MoveHints.DoesNotJump;
          return MoveHints.Queen;
        }
        if (dx % 15 == 0) 
        {
          for (var i = fromSquare - 15; i > toSquare; i -= 15)
            if (Squares[i] != 0) return MoveHints.Queen | MoveHints.DoesNotJump;
          return MoveHints.Queen;
        }
        if (dx > -8) 
        {
          for (var i = fromSquare - 1; i > toSquare; i -= 1)
            if (Squares[i] != 0) return MoveHints.Queen | MoveHints.DoesNotJump;
          return MoveHints.Queen;
        }
	  }
	  else
	  {
        if (dx % 17 == 0) 
        {
          for (var i = fromSquare + 17; i < toSquare; i += 17)
            if (Squares[i] != 0) return MoveHints.Queen | MoveHints.DoesNotJump;
          return MoveHints.Queen;
        }
        if (dx % 16 == 0) 
        {
          for (var i = fromSquare + 16; i < toSquare; i += 16)
            if (Squares[i] != 0) return MoveHints.Queen | MoveHints.DoesNotJump;
          return MoveHints.Queen;
        }
        if (dx % 15 == 0) 
        {
          for (var i = fromSquare + 15; i < toSquare; i += 15)
            if (Squares[i] != 0) return MoveHints.Queen | MoveHints.DoesNotJump;
          return MoveHints.Queen;
        }
        if (dx < 8) 
        {
          for (var i = fromSquare + 1; i < toSquare; i += 1)
            if (Squares[i] != 0) return MoveHints.Queen | MoveHints.DoesNotJump;
          return MoveHints.Queen;
        }
      }
      return MoveHints.Queen | MoveHints.DoesNotMoveThisWay;
    }
    private static MoveHints ValidateBlackKingMove(int fromSquare, int toSquare)
    {
	  var dx = toSquare - fromSquare;
      switch (dx)
      {      
        case 16:
          return MoveHints.King;
        case 17:
          return MoveHints.King;
        case 1:
          return MoveHints.King;
        case -15:
          return MoveHints.King;
        case -16:
          return MoveHints.King;
        case -17:
          return MoveHints.King;
        case -1:
          return MoveHints.King;
        case 15:
          return MoveHints.King;
      }
	  return MoveHints.King | MoveHints.DoesNotMoveThisWay;
    }
  
    private MoveHints ValidateMove(Piece piece, int fromSquare, int toSquare, Piece toPiece, CastlingAvailability castlingAvailability)
    {
	  switch (piece)
      {
        case Piece.WhitePawn:
          return ValidateWhitePawnMove(fromSquare, toSquare, toPiece);

        case Piece.WhiteBishop:
          return ValidateWhiteBishopMove(fromSquare, toSquare);

        case Piece.WhiteKnight:
          return ValidateWhiteKnightMove(fromSquare, toSquare);

        case Piece.WhiteRook:
          return ValidateWhiteRookMove(fromSquare, toSquare);

        case Piece.WhiteQueen:
          return ValidateWhiteQueenMove(fromSquare, toSquare);

        case Piece.WhiteKing:
          if (ValidateWhiteKingMove(fromSquare, toSquare) == MoveHints.King)
            return MoveHints.King;
		  return ValidateWhiteCastlingMove(fromSquare, toSquare, castlingAvailability);

        case Piece.BlackPawn:
          return ValidateBlackPawnMove(fromSquare, toSquare, toPiece);

        case Piece.BlackBishop:
          return ValidateBlackBishopMove(fromSquare, toSquare);

        case Piece.BlackKnight:
          return ValidateBlackKnightMove(fromSquare, toSquare);

        case Piece.BlackRook:
          return ValidateBlackRookMove(fromSquare, toSquare);

        case Piece.BlackQueen:
          return ValidateBlackQueenMove(fromSquare, toSquare);

        default:
        case Piece.BlackKing:
          if (ValidateBlackKingMove(fromSquare, toSquare) == MoveHints.King)
            return MoveHints.King;
		  return ValidateBlackCastlingMove(fromSquare, toSquare, castlingAvailability);

	  }
    }  
  }
}
